home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / mush6.4 / part07 < prev    next >
Encoding:
Internet Message Format  |  1989-03-12  |  48.6 KB

  1. Subject:  v18i029:  Mail user's shell version 6.4, Part07/19
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Dan Heller <island!argv@sun.com>
  7. Posting-number: Volume 18, Issue 29
  8. Archive-name: mush6.4/part07
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 7 (of 19)."
  19. # Contents:  fkeys.c folders.c init.c
  20. # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:13 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'fkeys.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'fkeys.c'\"
  24. else
  25. echo shar: Extracting \"'fkeys.c'\" \(13831 characters\)
  26. sed "s/^X//" >'fkeys.c' <<'END_OF_FILE'
  27. X/* @(#)fkeys.c        (c) copyright 10/18/86 (Dan Heller) */
  28. X
  29. X#include "mush.h"
  30. X#define draw(x1,y1,x2,y2,OP) pw_vector(msg_win, x1,y1,x2,y2,OP,1)
  31. X#define box(x1,y1,x2,y2,OP)  \
  32. X    draw(x1,y1, x1,y2,OP), draw(x1,y2, x2,y2,OP), \
  33. X        draw(x2,y2, x2,y1,OP), draw(x2,y1, x1,y1,OP)
  34. X
  35. Xstruct cmd fkey_cmds[] = {
  36. X    { "top", fkey_cmd }, { "close", fkey_cmd }, { "bottom", fkey_cmd },
  37. X    { "move", fkey_cmd }, { "stretch", fkey_cmd }, { "repaint", fkey_cmd },
  38. X    { "settings", fkey_settings }, { NULL, quit }
  39. X};
  40. X
  41. X#define L(n)        KEY_LEFTFIRST+(n)-1
  42. X#define R(n)        KEY_RIGHTFIRST+(n)-1
  43. X#define F(n)        KEY_TOPFIRST+(n)-1
  44. X#define BREAK_KEY    KEY_TOPLAST
  45. X
  46. Xchar *leftkey_default_settings[] = {
  47. X    "Left Function Key Settings",
  48. X    "Unused",        /* L1  */    "next",          /* L2  */
  49. X    "undelete",         /* L3  */    "delete",         /* L4  */
  50. X    "replyall",      /* L5  */    "replysender",       /* L6  */
  51. X    "mail",        /* L7  */    "Unset",        /* L8  */
  52. X    "lpr",          /* L9  */    "settings L",      /* L10 */
  53. X    0
  54. X};
  55. X
  56. Xchar *topkey_default_settings[] = {
  57. X    "Top Function Key Settings",
  58. X    "top",        /* T1  */     "close",            /* T2  */
  59. X    "move",        /* T3  */     "stretch",     /* T4  */
  60. X    "bottom",        /* T5  */     "repaint",       /* T6  */
  61. X    "Unset",        /* T7  */     "Unset",        /* T8  */
  62. X    "settings F",     /* T9  */
  63. X    0
  64. X};
  65. X
  66. Xchar *rightkey_default_settings[] = {
  67. X    "Right Function Key Settings",
  68. X    "Unset",        /* R1  */     "Unset",         /* R2  */
  69. X    "Unset",        /* R3  */     "Unset",         /* R4  */
  70. X    "Unset",        /* R5  */     "Unset",         /* R6  */
  71. X    "Unset",        /* R7  */     "Unset",         /* R8  */
  72. X    "Unset",        /* R9  */     "Unset",         /* R10 */
  73. X    "Unset",        /* R11 */     "Unset",         /* R12 */
  74. X    "Unset",        /* R13 */     "Unset",         /* R14 */
  75. X    "settings R",       /* R15 */
  76. X    0
  77. X};
  78. X
  79. X/*
  80. X * Execute commands defined by a function key.
  81. X * Left keys:
  82. X * L1 = (null)  can't be set
  83. X * L2 ... L10
  84. X * Top function keys
  85. X * F1 ... F9, BREAK/backspace (key not definable)
  86. X * Right function keys
  87. X * R1 ... R15
  88. X * Usually, the last Function key displays the others' settings.
  89. X */
  90. Xfkey(key)
  91. Xregister char *key;
  92. X{
  93. X    register char **argv, *p;
  94. X    char buf[256];
  95. X    int n;
  96. X
  97. X    /* user defined here...        ... default settings here */
  98. X    if (!strncmp((p = key_set_to(key)), "Un", 2)) {
  99. X    print("Funciton key: %s  %s", key, p);
  100. X    return 0;
  101. X    }
  102. X    /* make_command will screw up "p", so copy it first */
  103. X    (void) strcpy(buf, p);
  104. X    Debug("(%s) \"%s\": ", key, p), turnon(glob_flags, CONT_PRNT);
  105. X    if (argv = make_command(buf, TRPL_NULL, &n))
  106. X    (void) do_command(n, argv, msg_list);
  107. X    return -1;
  108. X}
  109. X
  110. Xfkey_settings(i, argv)
  111. Xregister char i;
  112. Xregister char **argv;
  113. X{
  114. X    register char key, *p, **fkey_str;
  115. X    char buf[256];
  116. X    char *help_args[17];
  117. X
  118. X    if (!*++argv) {
  119. X    print("Must specify one of L, F or R to identify a function key set");
  120. X    return -1;
  121. X    }
  122. X    key = **argv;
  123. X    switch(Upper(key)) {
  124. X    when 'L': fkey_str = leftkey_default_settings;
  125. X    when 'F': fkey_str = topkey_default_settings;
  126. X    when 'R': fkey_str = rightkey_default_settings;
  127. X    otherwise: print("Invalid key set: %c (choose L, F or R)", key);
  128. X           return -1;
  129. X    }
  130. X    help_args[0] = fkey_str[0];
  131. X    for (i = 1; fkey_str[i]; i++) {
  132. X    p = key_set_to(sprintf(buf, "%c%d", key, i));
  133. X    help_args[i] = savestr(sprintf(buf, "%c%-2.d       %s", key, i, p));
  134. X    }
  135. X    help_args[i] = 0;  /* null terminate list */
  136. X    (void) help(print_sw->ts_windowfd, help_args, NULL);
  137. X
  138. X    free_vec(help_args+1);
  139. X    return 0;
  140. X}
  141. X
  142. Xchar *
  143. Xkey_set_to(p)
  144. Xregister char *p;
  145. X{
  146. X    register char *p2, **fkey_str;
  147. X
  148. X    switch(*p) {
  149. X    when 'L': fkey_str = leftkey_default_settings;
  150. X    when 'F': fkey_str = topkey_default_settings;
  151. X    when 'R': fkey_str = rightkey_default_settings;
  152. X    }
  153. X    p2 = do_set(fkeys, p);
  154. X    return (p2)? p2: fkey_str[atoi(p+1)];
  155. X}
  156. X
  157. Xfkey_cmd(x, p)
  158. Xregister char **p;
  159. X{
  160. X    if (!strcmp(*p, "close"))
  161. X    toolquit(NO_ITEM, 0, NO_EVENT);
  162. X    else if (!strcmp(*p, "top"))
  163. X    wmgr_top(tool->tl_windowfd, rootfd);
  164. X    else if (!strcmp(*p, "move"))
  165. X    wmgr_move(tool->tl_windowfd, rootfd);
  166. X    else if (!strcmp(*p, "stretch"))
  167. X    wmgr_stretch(tool->tl_windowfd, rootfd);
  168. X    else if (!strcmp(*p, "bottom"))
  169. X    wmgr_bottom(tool->tl_windowfd, rootfd);
  170. X    else if (!strcmp(*p, "repaint"))
  171. X    wmgr_refreshwindow(tool->tl_windowfd, rootfd);
  172. X    return -1;
  173. X}
  174. X
  175. X/* execute a command given a function key, if the key is user defined,
  176. X * call fkey() at top of file. Parameter is the key number in "ascii"
  177. X */
  178. Xfunc_key(key)
  179. Xregister int key;
  180. X{
  181. X    register char *p;
  182. X    char buf[4];
  183. X    int nkey;
  184. X
  185. X    if (key >= KEY_LEFTFIRST && key <= KEY_LEFTLAST)
  186. X    buf[0] = 'L', nkey = key - KEY_LEFTFIRST;
  187. X    else if (key >= KEY_TOPFIRST && key <= KEY_TOPLAST)
  188. X    buf[0] = 'F', nkey = key - KEY_TOPFIRST;
  189. X    else if (key >= KEY_RIGHTFIRST && key <= KEY_RIGHTLAST)
  190. X    buf[0] = 'R', nkey = key - KEY_RIGHTFIRST;
  191. X    (void) sprintf(buf+1, "%d", nkey+1);
  192. X
  193. X    return fkey(buf);
  194. X}
  195. X
  196. Xvoid
  197. Xset_fkeys()
  198. X{
  199. X    ready(display_keys() + 10);
  200. X    print_valid_functions(txt.y+20);
  201. X    getting_opts = 2;
  202. X    win_setcursor(msg_sw->ts_windowfd, &checkmark);
  203. X}
  204. X
  205. Xchar *MSG = "Click the appropriate mouse button over a function key";
  206. Xready(Y)
  207. X{
  208. X    static int y;
  209. X    int x = (msg_rect.r_width - strlen(MSG)*l_width(LARGE))/2;
  210. X    if (Y)
  211. X    y = Y;
  212. X    Clrtoeol(msg_win, (txt.x = 0), (txt.y = y), LARGE);
  213. X    highlight(msg_win, x, y, LARGE, MSG);
  214. X}
  215. X
  216. X/* number of pixels in x and y directions describing the size of a graphical
  217. X * function key.  they represent the little keys and big keys respectively.
  218. X */
  219. X/* static struct pr_pos fkey_sizes[2] = { { 23, 23 }, { 50, 23 } }; */
  220. Xstatic struct pr_pos fkey_sizes[2] = { { 24, 23 }, { 52, 23 } };
  221. X
  222. X#define BORDER        4   /* border (distance) between keys */
  223. X#define KEYTOP        15  /* distance from top to start drawing */
  224. X#define LEFT_START    15  /* pixels from left to start drawing boxes */
  225. X#define TOP_START    (LEFT_START+2*fkey_sizes[0].x + fkey_sizes[1].x+BORDER)
  226. X#define RIGHT_START    (TOP_START + 5*(fkey_sizes[0].x+BORDER) + \
  227. X                     5*(fkey_sizes[1].x+BORDER))
  228. X
  229. X/*
  230. X * if !p, we're setting key at location x,y.
  231. X * else Set that key to this string (p).
  232. X */
  233. Xvoid
  234. Xset_key(p, x,y)
  235. Xregister char *p;
  236. Xregister int x,y;
  237. X{
  238. X    char     buf[256], **argv;
  239. X    static char *key;
  240. X    int     argc;
  241. X
  242. X    static int key_x, key_y;
  243. X    if (!p) {
  244. X    if (key = find_key(x,y)) {
  245. X        print("Type new setting for key: %s", key);
  246. X        (void) sprintf(buf, "Function key \"%s\": ", key);
  247. X        highlight(msg_win, 20, txt.y, LARGE, buf);
  248. X        txt.x = 20 + strlen(buf)*l_width(LARGE);
  249. X        Clrtoeol(msg_win, txt.x, txt.y, LARGE);
  250. X        type_cursor(PIX_SRC);
  251. X    } else
  252. X        ready(0);
  253. X    key_x = x, key_y = y;
  254. X    } else {
  255. X    u_long save_bang = ison(glob_flags, IGN_BANG);
  256. X    if (!*p)
  257. X        (void) sprintf(buf, "unfkey %s", key);
  258. X    else
  259. X        (void) sprintf(buf, "fkey %s \"%s\"", key, p);
  260. X    turnon(glob_flags, IGN_BANG);
  261. X    if (argv = make_command(buf, TRPL_NULL, &argc)) {
  262. X        (void) do_command(argc, argv, msg_list);
  263. X        print("Function key %s:  %s", key, key_set_to(key));
  264. X    }
  265. X    if (!save_bang)
  266. X        turnoff(glob_flags, IGN_BANG);
  267. X    ready(0);
  268. X    }
  269. X}
  270. X
  271. X/* passed the x and y coords of a mouse click, return the function key
  272. X * that exists in that position. NULL if no key there.  string will be
  273. X * something like "L6" or "F9" or "R12"
  274. X */
  275. Xchar *
  276. Xfind_key(x,y)
  277. Xint x, y;
  278. X{
  279. X    static char buf[6];
  280. X    int row, col;
  281. X    static int old_left, old_top, old_right, old_bot;
  282. X
  283. X    if (!(row = find_y(&y)))
  284. X    return NULL;
  285. X    if (x < LEFT_START || x > RIGHT_START + 3*(fkey_sizes[0].x+BORDER))
  286. X    return NULL;   /* out of range */
  287. X    if (x > LEFT_START && x < TOP_START-fkey_sizes[0].x - BORDER) {
  288. X    if ((col = (x > LEFT_START + fkey_sizes[0].x + BORDER)+1) == 1)
  289. X        x = LEFT_START+1;
  290. X    else x = LEFT_START + fkey_sizes[0].x + BORDER + 1;
  291. X    if (col == 1 && row == 1)
  292. X        return NULL;
  293. X    /* unhighlight the old function key image */
  294. X    if (old_left)
  295. X        box(old_left, old_top, old_right, old_bot, PIX_CLR);
  296. X    old_left = x, old_top = y;
  297. X    old_right = x+fkey_sizes[(col != 1)].x-2, old_bot = y+fkey_sizes[0].y-2;
  298. X    /* highlight most recently selected function key image */
  299. X    box(x,y, old_right, old_bot, PIX_SRC);
  300. X
  301. X    return sprintf(buf, "L%d", col + 2*(row-1));
  302. X    }
  303. X    if (x > TOP_START && x < RIGHT_START - fkey_sizes[0].x - BORDER) {
  304. X    int which;
  305. X    if (row > 1)
  306. X        return NULL;
  307. X    which = (x - TOP_START) / (fkey_sizes[0].x + BORDER) + 1;
  308. X    if (which == 15)
  309. X        return NULL;   /* Can't set break key (backspace on a sun3) */
  310. X    if (which == 14)
  311. X        x = TOP_START + ((which = 9)-2) * (fkey_sizes[1].x+BORDER) -
  312. X            fkey_sizes[0].x - BORDER + 1;
  313. X    else if (which <= 2)
  314. X        x = TOP_START + (which-1) * (fkey_sizes[0].x+BORDER) + 1;
  315. X    else {
  316. X        which = (which+3)/2;
  317. X        x = TOP_START + (which-2) * (fkey_sizes[1].x+BORDER) + 1;
  318. X    }
  319. X
  320. X    /* unhighlight the old function key image */
  321. X    if (old_left)
  322. X        box(old_left, old_top, old_right, old_bot, PIX_CLR);
  323. X    old_left = x, old_top = y;
  324. X    old_right = x+fkey_sizes[(which > 2 && which < 8)].x-2;
  325. X    old_bot = y+fkey_sizes[0].y-2;
  326. X    /* highlight most recently selected function key image */
  327. X    box(x,y, old_right, old_bot, PIX_SRC);
  328. X
  329. X    return sprintf(buf, "F%d", which);
  330. X    }
  331. X    if (x > RIGHT_START) {
  332. X    if (x < RIGHT_START + fkey_sizes[0].x)
  333. X        x = RIGHT_START+1, col = 1;
  334. X    else if (x < RIGHT_START + fkey_sizes[0].x + BORDER)
  335. X        return NULL;  /* cursor was clicked between keys */
  336. X    else if (x < RIGHT_START + 2*fkey_sizes[0].x + BORDER)
  337. X        x = RIGHT_START+fkey_sizes[0].x+BORDER+1, col = 2;
  338. X    else if (x < RIGHT_START + 2 * (fkey_sizes[0].x+BORDER))
  339. X        return NULL;  /* click between keys again */
  340. X    else x = RIGHT_START + 2*(fkey_sizes[0].x+BORDER)+1, col = 3;
  341. X
  342. X    /* unhighlight the old function key image */
  343. X    if (old_left)
  344. X        box(old_left, old_top, old_right, old_bot, PIX_CLR);
  345. X    old_left = x, old_top = y;
  346. X    old_right = x+fkey_sizes[0].x-2, old_bot = y+fkey_sizes[0].y-2;
  347. X    /* highlight most recently selected function key image */
  348. X    box(x,y, old_right, old_bot, PIX_SRC);
  349. X
  350. X    return sprintf(buf, "R%d", col + 3*(row-1));
  351. X    }
  352. X    return NULL;
  353. X}
  354. X
  355. X/* find_y will find which row in a function key pad a y coordinate
  356. X * represents. return 1,2,3,4, or 5   0 if inbetween rows
  357. X */
  358. Xfind_y(y)
  359. Xregister int *y;
  360. X{
  361. X    int Y, y_incr = fkey_sizes[0].y, ret_value = 0;
  362. X    for (Y = KEYTOP; Y <= KEYTOP + 6*y_incr + 4 * BORDER; Y += y_incr + BORDER)
  363. X    if (*y < Y) {
  364. X        *y = (Y - y_incr - BORDER) + 1;
  365. X        return ret_value;
  366. X    } else ret_value++;
  367. X    return 0;
  368. X}
  369. X
  370. Xchar *l_msg = "Specifies which function key for setting value";
  371. Xchar *m_msg = "Display current value for function key";
  372. Xchar *r_msg = "Help setting and viewing function key values";
  373. X
  374. Xdisplay_keys()
  375. X{
  376. X    register int i, x,y;
  377. X    register char *p;
  378. X
  379. X    do_clear();
  380. X
  381. X    x = LEFT_START, y = KEYTOP;
  382. X    /* print left keys */
  383. X    for (i = 0; i < 10; i++) {
  384. X    box(x, y, x + fkey_sizes[i%2].x, y + fkey_sizes[i%2].y, PIX_SRC);
  385. X    box(x+2, y+2, x+fkey_sizes[i%2].x-2, y+fkey_sizes[i%2].y-2, PIX_SRC);
  386. X    if (i && (p = find_key(x+4,y+4)))
  387. X        pw_text(msg_win, x+3, y+3+l_height(SMALL), PIX_SRC,fonts[SMALL], p);
  388. X    else pw_replrop(msg_win, x+3, y+3, fkey_sizes[0].x-5, fkey_sizes[0].y-5,
  389. X         PIX_SRC | PIX_DST, &shade_50, 0,0);
  390. X    if (i % 2)
  391. X        y += fkey_sizes[0].y + BORDER, x = LEFT_START;
  392. X    else
  393. X        x += fkey_sizes[0].x + BORDER;
  394. X    }
  395. X
  396. X    x = TOP_START, y = KEYTOP;
  397. X    /* print top keys */
  398. X    for (i = 1; i <= 10; i++) {
  399. X    register int n = (i >= 3 && i <= 7);
  400. X    box(x, y, x + fkey_sizes[n].x, y + fkey_sizes[n].y, PIX_SRC);
  401. X    box(x+2, y+2, x + fkey_sizes[n].x-2, y + fkey_sizes[n].y-2, PIX_SRC);
  402. X    if (i != 10 && (p = find_key(x+4,y+4)))
  403. X        pw_text(msg_win, x+3, y+3+l_height(SMALL), PIX_SRC,fonts[SMALL], p);
  404. X    /* shade the break key (backspace on sun3's) -- can't set */
  405. X    else if (i == 10)
  406. X        pw_replrop(msg_win, x+3, y+3, fkey_sizes[n].x-5, fkey_sizes[n].y-5,
  407. X         PIX_SRC | PIX_DST, &shade_50, 0,0);
  408. X    x += fkey_sizes[n].x + BORDER;
  409. X    }
  410. X
  411. X    x = RIGHT_START;
  412. X    /* print right keys */
  413. X    for (i = 0; i < 15; i++) {
  414. X    box(x, y, x + fkey_sizes[0].x, y + fkey_sizes[0].y, PIX_SRC);
  415. X    box(x+2, y+2, x + fkey_sizes[0].x-2, y + fkey_sizes[0].y-2, PIX_SRC);
  416. X    if (p = find_key(x+4,y+4))
  417. X        pw_text(msg_win, x+3, y+3+l_height(SMALL),PIX_SRC, fonts[SMALL], p);
  418. X    if (!((i+1) % 3))
  419. X        y += fkey_sizes[0].y + BORDER, x -= 2*(fkey_sizes[0].x + BORDER);
  420. X    else
  421. X        x += fkey_sizes[0].x + BORDER;
  422. X    }
  423. X    x = TOP_START;
  424. X    y = KEYTOP + BORDER + fkey_sizes[0].y + l_height(DEFAULT);
  425. X    pw_rop(msg_win, x, y-11, 16,16, PIX_SRC, &mouse_left, 0,0);
  426. X    pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], l_msg);
  427. X
  428. X    y += BORDER + fkey_sizes[0].y;
  429. X    pw_rop(msg_win, x,y-11, 16,16, PIX_SRC, &mouse_middle, 0,0);
  430. X    pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], m_msg);
  431. X
  432. X    y += BORDER + fkey_sizes[0].y;
  433. X    pw_rop(msg_win, x,y-11, 16,16, PIX_SRC, &mouse_right, 0,0);
  434. X    pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], r_msg);
  435. X
  436. X    x = (msg_rect.r_width - 26*l_width(DEFAULT))/2;
  437. X    y += BORDER + fkey_sizes[0].y;
  438. X    highlight(msg_win, x, y, DEFAULT, "You may not set shaded keys");
  439. X
  440. X    y += BORDER + fkey_sizes[0].y + 15;
  441. X    for (i = 0; i < BORDER; i++)
  442. X    draw(0, y+i, msg_rect.r_width, y+i, PIX_SRC);
  443. X    y += 10;
  444. X    for (i = 0; i < BORDER; i++)
  445. X    draw(0, y+l_height(LARGE)+i, msg_rect.r_width, y+l_height(LARGE)+i,
  446. X         PIX_SRC);
  447. X    return y;
  448. X}
  449. X
  450. Xprint_valid_functions(y)
  451. Xregister int y;
  452. X{
  453. X    register int x, n, cmd_len = 12 * l_width(DEFAULT);
  454. X    register char *p;
  455. X
  456. X    y += 20, x = (msg_rect.r_width - 25*l_width(LARGE))/2;
  457. X    highlight (msg_win, x, y, LARGE, "Available Command Names");
  458. X    y += 20, x = 30;
  459. X    for (n = 0; p = cmds[n].command; n++) {
  460. X    if (x + cmd_len > msg_rect.r_width - 5)
  461. X        y += l_height(DEFAULT), x = 30;
  462. X    pw_text(msg_win, x, y, PIX_SRC, fonts[DEFAULT], p);
  463. X    x += cmd_len;
  464. X    }
  465. X    for (n = 0; p = fkey_cmds[n].command; n++) {
  466. X    if (x + cmd_len > msg_rect.r_width - 5)
  467. X        y += l_height(DEFAULT), x = 30;
  468. X    pw_text(msg_win, x, y, PIX_SRC, fonts[DEFAULT], p);
  469. X    x += cmd_len;
  470. X    }
  471. X}
  472. END_OF_FILE
  473. if test 13831 -ne `wc -c <'fkeys.c'`; then
  474.     echo shar: \"'fkeys.c'\" unpacked with wrong size!
  475. fi
  476. # end of 'fkeys.c'
  477. fi
  478. if test -f 'folders.c' -a "${1}" != "-c" ; then 
  479.   echo shar: Will not clobber existing file \"'folders.c'\"
  480. else
  481. echo shar: Extracting \"'folders.c'\" \(16743 characters\)
  482. sed "s/^X//" >'folders.c' <<'END_OF_FILE'
  483. X/* @(#)folders.c    (c) copyright 10/18/86 (Dan Heller) */
  484. X
  485. X#include "mush.h"
  486. X
  487. Xstatic char oldfolder[MAXPATHLEN];
  488. X
  489. X/* folder %[user]  --new mailfile is the spool/mail/login file [user].
  490. X * folder #  --new mailfile is the folder previous to the current folder
  491. X * folder &  --new mailfile is ~/mbox (or whatever "mbox" is set to)
  492. X * folder +file --new mailfile is in the directory "folder"; name is 'file'
  493. X * folder "path" --full path name or the one in current working directory.
  494. X *
  495. X * in all cases, changes are updated unless a '!' is specified after the
  496. X * folder command (e.g. "f!", "folder !" "fo!" .. all permutations)
  497. X * as usual, if new mail has arrived before the file is copied back, then
  498. X * user will be notified beforehand.
  499. X *
  500. X * RETURN -1 on error -- else return 0. All bits in msg_list are set to true.
  501. X */
  502. Xfolder(argc, argv, list)
  503. Xregister char **argv, list[];
  504. X{
  505. X    int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0;
  506. X    char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
  507. X    struct stat statbuf;
  508. X    extern long last_spool_size;
  509. X
  510. X    if (ison(glob_flags, IS_PIPE)) {
  511. X    print("You can't pipe to the %s command.\n", *argv);
  512. X    return -1;
  513. X    } else if (ison(glob_flags, IS_SENDING)) {
  514. X    print("You can't use the %s command while sending.\n", *argv);
  515. X    return -1;
  516. X    }
  517. X    while (*++argv && (**argv == '-' || **argv == '!'))
  518. X    if (!strcmp(*argv, "-?"))
  519. X        return help(0, "folder", cmd_help);
  520. X    else if (!strcmp(*argv, "-N"))
  521. X        no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES));
  522. X    else if (!strcmp(*argv, "-r"))
  523. X        do_read_only = 1;
  524. X    else if (!strcmp(*argv, "!"))
  525. X        turnoff(glob_flags, DO_UPDATE);
  526. X
  527. X    if (updating) {
  528. X    (void) strcpy(buf, mailfile);
  529. X    if (ison(glob_flags, READ_ONLY))
  530. X        do_read_only = 1;
  531. X    } else {
  532. X    if (!*argv) {
  533. X        mail_status(0);
  534. X        return 0;
  535. X    }
  536. X    if (!strcmp(*argv, "#"))
  537. X        if (!*oldfolder) {
  538. X        print("No previous folder\n");
  539. X        return -1;
  540. X        } else
  541. X        newfolder = oldfolder;
  542. X    else if (!strcmp(*argv, "&")) {
  543. X        if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
  544. X        newfolder = DEF_MBOX;
  545. X    } else
  546. X        newfolder = *argv;
  547. X    n = 0;
  548. X    tmp = getpath(newfolder, &n);
  549. X    if (n == -1) {
  550. X        print("%s: %s\n", newfolder, tmp);
  551. X        return -1;
  552. X    } else if (n == 1) {
  553. X        print("%s: is a directory\n", tmp);
  554. X        return -1;
  555. X    }
  556. X    /* strcpy so copyback() below (which calls getpath) doesn't change
  557. X     * the data that tmp intended to point to.
  558. X     */
  559. X    (void) strcpy(buf, tmp);
  560. X    }
  561. X    if (stat(buf, &statbuf) == -1 || !(statbuf.st_mode & 0400)) {
  562. X    error("Unable to read %s", buf);
  563. X    return -1;
  564. X    }
  565. X    /* If the file can't be opened for writing, autoset READ_ONLY */
  566. X    if (!(statbuf.st_mode & 0200))
  567. X    do_read_only = 1;
  568. X#ifdef SUNTOOL
  569. X    if (istool) lock_cursors();
  570. X#endif /* SUNTOOL */
  571. X
  572. X    if (!copyback(updating ? "Update folder?" : "Change anyway?")) {
  573. X#ifdef SUNTOOL
  574. X    if (istool) unlock_cursors();
  575. X#endif /* SUNTOOL */
  576. X    /* an error occured updating the folder */
  577. X    return -1;
  578. X    }
  579. X    if (strcmp(mailfile, buf)) {
  580. X    if (!updating)
  581. X        (void) strcpy(oldfolder, mailfile);
  582. X    strdup(mailfile, buf);
  583. X    }
  584. X    do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY);
  585. X    last_size = spool_size = 0L;
  586. X    while (msg_cnt--) {
  587. X    xfree(msg[msg_cnt].m_date_recv);
  588. X    xfree(msg[msg_cnt].m_date_sent);
  589. X    msg[msg_cnt].m_date_recv = msg[msg_cnt].m_date_sent = NO_STRING;
  590. X    }
  591. X    msg_cnt = 0, msg[0].m_offset = 0L;
  592. X    turnoff(glob_flags, CONT_PRNT);
  593. X
  594. X    turnon(glob_flags, IGN_SIGS);
  595. X    /* clear the tempfile */
  596. X    if (tmpf)
  597. X    (void) fclose(tmpf);
  598. X    if (!do_read_only) {
  599. X    if (!(tmpf = mask_fopen(tempfile, "w"))) {
  600. X        error("error truncating %s", tempfile);
  601. X        turnoff(glob_flags, IGN_SIGS);
  602. X        return -1;
  603. X    }
  604. X    }
  605. X    (void) load_folder(mailfile, TRUE, NULL);
  606. X    if (do_read_only && !(tmpf = fopen(mailfile, "r"))) {
  607. X    error(mailfile);
  608. X    turnoff(glob_flags, IGN_SIGS);
  609. X    return -1;
  610. X    }
  611. X    last_msg_cnt = msg_cnt;  /* for check_new_mail */
  612. X    (void) mail_size();
  613. X    last_spool_size = spool_size;    /* prevents bogus "new mail" messages */
  614. X#ifdef SUNTOOL
  615. X    if (istool) {
  616. X    panel_set(next_scr, PANEL_SHOW_ITEM, FALSE, 0);
  617. X    panel_set(prev_scr, PANEL_SHOW_ITEM, FALSE, 0);
  618. X    pw_rop(hdr_win, 0,0, hdr_rect.r_width, hdr_rect.r_height,PIX_CLR,0,0,0);
  619. X    if (!msg_cnt) {
  620. X        add_folder_to_menu(folder_item, 3);
  621. X        add_folder_to_menu(save_item, 1);
  622. X    }
  623. X    }
  624. X#endif /* SUNTOOL */
  625. X    current_msg = 0;
  626. X    turnoff(glob_flags, IGN_SIGS);
  627. X
  628. X    /* now sort messages according a user-defined default */
  629. X    if (!updating && msg_cnt > 1 && !strcmp(mailfile, spoolfile) &&
  630. X        (tmp = do_set(set_options, "sort"))) {
  631. X    (void) sprintf(buf, "sort %s", tmp);
  632. X    if (argv = make_command(buf, TRPL_NULL, &argc)) {
  633. X        /* msg_list can't be null for do_command and since we're not
  634. X         * interested in the result, call sort directly
  635. X         */
  636. X        (void) sort(argc, argv, NULL);
  637. X        free_vec(argv);
  638. X    }
  639. X    }
  640. X    turnoff(glob_flags, DO_UPDATE);
  641. X
  642. X    /* go to first NEW message */
  643. X    while (current_msg < msg_cnt && ison(msg[current_msg].m_flags, OLD))
  644. X    current_msg++;
  645. X    if (current_msg == msg_cnt)
  646. X    /* no new message found -- try first unread message */
  647. X    for (current_msg = 0;
  648. X         current_msg < msg_cnt && isoff(msg[current_msg].m_flags, UNREAD);
  649. X         current_msg++)
  650. X         ;
  651. X    if (current_msg == msg_cnt)
  652. X    current_msg = 0;
  653. X
  654. X    if ((!istool || istool && !msg_cnt) && !iscurses)
  655. X    mail_status(0);
  656. X    /* be quiet if we're piping */
  657. X    if ((istool || !updating) && isoff(glob_flags, DO_PIPE) &&
  658. X    (istool || !no_hdrs) && msg_cnt)
  659. X    (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list);
  660. X#ifdef SUNTOOL
  661. X    if (istool) {
  662. X    if (!msg_cnt)
  663. X        print("No Mail in %s\n", mailfile);
  664. X    if (!getting_opts)
  665. X        if (msg_cnt && isoff(glob_flags, IS_GETTING))
  666. X        display_msg(current_msg, (long)0);
  667. X        else
  668. X        do_clear();
  669. X    unlock_cursors();
  670. X    }
  671. X#endif /* SUNTOOL */
  672. X    if (list) {
  673. X    clear_msg_list(list);
  674. X    bitput(list, list, msg_cnt, =~) /* macro */
  675. X    }
  676. X    return 0;
  677. X}
  678. X
  679. Xfolders(argc, argv)
  680. Xregister char **argv;
  681. X{
  682. X    register char *p;
  683. X    char buf[128], unused[MAXMSGS_BITS];
  684. X
  685. X    if (!(p = do_set(set_options, "folder")) || !*p)
  686. X    p = DEF_FOLDER;
  687. X    (void) sprintf(buf, "ls %s", p);
  688. X    if (argv = make_command(buf, TRPL_NULL, &argc))
  689. X    return do_command(argc, argv, unused);
  690. X    return -1;
  691. X}
  692. X
  693. X/* merge_folders filename  -- concatenate the folder specified by filename
  694. X *                            to the current folder.
  695. X *
  696. X * RETURN -1 on error -- else return 0.  A bit in msg_list is set to true
  697. X * for each of the "new" messages read in to the current folder.
  698. X */
  699. Xmerge_folders(n, argv, list)
  700. Xregister char **argv, list[];
  701. X{
  702. X    int no_hdrs = 0, newest_msg;
  703. X    long orig_offset;
  704. X    char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
  705. X
  706. X    if (ison(glob_flags, IS_PIPE)) {
  707. X    print("You can't pipe to the %s command.\n", *argv);
  708. X    return -1;
  709. X    } else if (ison(glob_flags, IS_SENDING)) {
  710. X    print("You can't use the %s command while sending.\n", *argv);
  711. X    return -1;
  712. X    }
  713. X
  714. X    while (*++argv && **argv == '-')
  715. X    if (!strcmp(*argv, "-?"))
  716. X        return help(0, "merge", cmd_help);
  717. X    else if (!strcmp(*argv, "-N"))
  718. X        no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES));
  719. X
  720. X    if (!*argv)
  721. X    return 0;
  722. X
  723. X    if (ison(glob_flags, READ_ONLY)) {
  724. X    print("Folder is read-only.\n");
  725. X    return -1;
  726. X    }
  727. X
  728. X    if (!strcmp(*argv, "#"))
  729. X    if (!*oldfolder) {
  730. X        print("No previous folder\n");
  731. X        return -1;
  732. X    } else
  733. X        newfolder = oldfolder;
  734. X    else if (!strcmp(*argv, "&")) {
  735. X    if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
  736. X        newfolder = DEF_MBOX;
  737. X    } else
  738. X    newfolder = *argv;
  739. X    n = 0;
  740. X    tmp = getpath(newfolder, &n);
  741. X    if (n == -1) {
  742. X    print("%s: %s\n", newfolder, tmp);
  743. X    return -1;
  744. X    } else if (n == 1) {
  745. X    print("%s: is a directory\n", tmp);
  746. X    return -1;
  747. X    }
  748. X
  749. X    turnon(glob_flags, IGN_SIGS);
  750. X    orig_offset = msg[msg_cnt].m_offset;
  751. X    (void) load_folder(tmp, 2, list);
  752. X    msg[msg_cnt].m_offset = orig_offset;
  753. X    newest_msg = last_msg_cnt;
  754. X    Debug("newest_msg = %d\n", newest_msg);
  755. X    last_msg_cnt = msg_cnt;  /* for check_new_mail */
  756. X    Debug("msg_cnt = %d\n", msg_cnt);
  757. X    (void) mail_size();
  758. X    turnoff(glob_flags, IGN_SIGS);
  759. X
  760. X    if ((!istool || istool && !msg_cnt)
  761. X        && !iscurses && !ison(glob_flags, PRE_CURSES))
  762. X    mail_status(0);
  763. X    /* be quiet if we're piping or if told not to show headers */
  764. X    if ((istool || !no_hdrs) && isoff(glob_flags, DO_PIPE)
  765. X        && newest_msg < msg_cnt)
  766. X    (void) cmd_line(sprintf(buf, "headers %d", newest_msg + 1), NULL);
  767. X    return 0;
  768. X}
  769. X
  770. X/*
  771. X * Undigestify messages.  If a message is in digest-format, there are many
  772. X * messages within this message which are to be extracted.  Kinda like a
  773. X * folder within a folder.  By default, this routine will create a new
  774. X * folder that contains the new messages.  -m option will merge the new
  775. X * messages into the current folder.
  776. X */
  777. Xdo_undigest(n, argv, list)
  778. Xchar *argv[], list[];
  779. X{
  780. X    int r, articles = 0, merge = 0, appending = 0;
  781. X    char buf[MAXPATHLEN], cmdbuf[MAXPATHLEN], newlist[MAXMSGS_BITS], *dir, c;
  782. X    FILE *fp;
  783. X
  784. X    while (argv && *++argv && **argv == '-') {
  785. X    n = 1;
  786. X    while (c = argv[0][n++])
  787. X        switch(c) {
  788. X        case 'm':
  789. X            if (ison(glob_flags, READ_ONLY)) {
  790. X            print("Folder is read only.\n");
  791. X            return -1;
  792. X            }
  793. X            merge++;
  794. X        otherwise: return help(0, "undigest", cmd_help);
  795. X        }
  796. X    }
  797. X
  798. X    if ((n = get_msg_list(argv, list)) == -1)
  799. X    return -1;
  800. X
  801. X    argv += n;
  802. X
  803. X    if (*argv) {
  804. X    int isdir = 1; /* Ignore file nonexistance errors */
  805. X    (void) strcpy(buf, getpath(*argv, &isdir));
  806. X    if (isdir < 0) {
  807. X        print("%s: %s\n", *argv, buf);
  808. X        return -1;
  809. X    } else if (isdir == 1) {
  810. X        print("%s: is a directory\n", buf);
  811. X        return -1;
  812. X    }
  813. X    } else {
  814. X    register char *p, *p2;
  815. X    if (Access(dir = ".", W_OK) &&
  816. X        !(dir = do_set(set_options, "folder")) &&
  817. X        !(dir = do_set(set_options, "tmpdir")))
  818. Xalted:
  819. X        dir = ALTERNATE_HOME;
  820. X    for (n = 0; n < msg_cnt; n++)
  821. X        if (msg_bit(list, n))
  822. X        break;
  823. X
  824. X    if (!(p = header_field(n, "subject")))
  825. X        (void) mktemp(sprintf(buf, "%s/digestXXXXX", dir));
  826. X    else {
  827. X        if (!lcase_strncmp(p, "re: ", 4))
  828. X        p += 4;
  829. X        for (p2 = p; *p2; p2++)
  830. X        if (!isalnum(*p2) && *p2 != '-' && *p2 != '.') {
  831. X            *p2 = 0;
  832. X            break;
  833. X        }
  834. X        p2 = buf + Strcpy(buf, dir);
  835. X        *p2++ = '/';
  836. X        (void) strcpy(p2, p);
  837. X    }
  838. X    }
  839. X
  840. X    if (!Access(buf, W_OK)) {
  841. X    fp = mask_fopen(buf, "a");
  842. X    appending = (fp > 0);
  843. X    } else
  844. X    fp = mask_fopen(buf, "w");
  845. X    if (!fp) {
  846. X    if (!*argv && strcmp(dir, ALTERNATE_HOME))
  847. X        goto alted;
  848. X    error("can't create %s", buf);
  849. X    return -1;
  850. X    }
  851. X
  852. X    for (n = 0; n < msg_cnt; n++) {
  853. X    if (!msg_bit(list, n))
  854. X        continue;
  855. X
  856. X    print("undigesting message %d\n", n+1);
  857. X    /* copy message into file making sure all headers exist. */
  858. X    r = undigest(n, fp);
  859. X    if (r <= 0)
  860. X        break;
  861. X    articles += r;
  862. X    }
  863. X    fclose(fp);
  864. X    if (r <= 0) {
  865. X    if (!appending)
  866. X        unlink(buf);
  867. X    return -1;
  868. X    }
  869. X    if (merge) {
  870. X    (void) cmd_line(sprintf(cmdbuf, "\\merge -N %s", buf), newlist);
  871. X    (void) unlink(buf);
  872. X    print("Merged in %d messages.\n", articles);
  873. X    } else
  874. X    print("Added %d messages to \"%s\".\n", articles, buf);
  875. X    clear_msg_list(list);
  876. X    for (n = 0; n < msg_cnt; n++)
  877. X    if (msg_bit(newlist, n))
  878. X        set_msg_bit(list, n);
  879. X    return 0;
  880. X}
  881. X
  882. X/*
  883. X * split digest-message 'n' to file "fp".
  884. X * return number of articles copied or -1 if system error on fputs.
  885. X * A digest is a folder-in-a-message in a special, semi-standard form.
  886. X */
  887. Xundigest(n, fp)
  888. Xregister int n;
  889. Xregister FILE *fp;
  890. X{
  891. X    int  art_cnt = 0, on_hdr = -1; /* on_hdr is -1 if hdr not yet found */
  892. X    long get_hdr = 0L;
  893. X    char from[HDRSIZ], line[HDRSIZ], last_sep[HDRSIZ];
  894. X    char from_hdr[256], afrom[256], adate[64];
  895. X    char *fdate = "Xxx Xxx 00 00:00:00 0000"; /* Dummy date in ctime form */
  896. X    SIGRET (*oldint)(), (*oldquit)();
  897. X
  898. X    if (!msg_get(n, from, sizeof from)) {
  899. X    error("Unable to find msg %d", n+1);
  900. X    return -1;
  901. X    }
  902. X#ifndef MSG_SEPARATOR
  903. X    else {
  904. X    char *p = from + 5;
  905. X    skipspaces(0);
  906. X    p = index(p, ' ');
  907. X    if (p) {
  908. X        skipspaces(0);
  909. X        fdate = p;
  910. X    }
  911. X    if (fputs(from, fp) == EOF)
  912. X        return -1;
  913. X    }
  914. X#endif /* !MSG_SEPARATOR */
  915. X
  916. X    on_intr();
  917. X    *afrom = *adate = *last_sep = '\0';
  918. X    while (ftell(tmpf) < msg[n].m_offset + msg[n].m_size &&
  919. X       fgets(line, sizeof (line), tmpf)) {
  920. X    if (ison(glob_flags, WAS_INTR))
  921. X        goto handle_error;
  922. X    if (*line == '\n' && on_hdr > 0)    /* blank line -- end of header */
  923. X        on_hdr = 0;
  924. X
  925. X    /* Check for the beginning of a digest article */
  926. X    if (!strncmp(line, "--------", 8)) {
  927. X        if (get_hdr) {
  928. X        if (do_set(set_options, "warning"))
  929. X            wprint("Article with no header? (added to article #%d)\n",
  930. X                art_cnt);
  931. X        /* Don't start a new message for whatever this is,
  932. X         * just fseek back and keep appending to the last one.
  933. X         */
  934. X        if (fseek(tmpf, get_hdr, L_SET) < 0 ||
  935. X            fputs(last_sep, fp) == EOF) {
  936. X            art_cnt = -1;
  937. X            goto handle_error;
  938. X        }
  939. X        get_hdr = 0L;
  940. X        on_hdr = 0;
  941. X        } else {
  942. X        (void) strcpy(last_sep, line);
  943. X        get_hdr = ftell(tmpf);
  944. X        *afrom = *adate = '\0';
  945. X        on_hdr = -1;    /* Haven't found the new header yet */
  946. X        }
  947. X        continue;
  948. X    }
  949. X
  950. X    if (get_hdr) {
  951. X        char *p = *line == '>' ? line + 1 : line;
  952. X        if (*line == '\n') {
  953. X        if (*afrom || *adate) {
  954. X            (void) fseek(tmpf, get_hdr, L_SET);
  955. X            /* Terminate the previous article */
  956. X            art_cnt++;
  957. X#ifdef MSG_SEPARATOR
  958. X#ifdef END_MSG_SEP
  959. X            if (fputs(END_MSG_SEP, fp) == EOF) {
  960. X            art_cnt = -1;
  961. X            goto handle_error;
  962. X            }
  963. X#endif /* END_MSG_SEP */
  964. X#ifdef MMDF
  965. X            /* MMDF has a newline in MSG_SEPARATOR */
  966. X            if (fputs(MSG_SEPARATOR, fp) == EOF)
  967. X#else /* !MMDF */
  968. X            /* Other MSG_SEPARATORs need a newline */
  969. X            if (fputs(MSG_SEPARATOR, fp) == EOF ||
  970. X                fputc('\n', fp) == EOF)
  971. X#endif /* MMDF */
  972. X#else /* !MSG_SEPARATOR */
  973. X            /* Everybody else needs a From_ line */
  974. X            if (fprintf(fp, "From %s  %s", *afrom ? afrom : "unknown",
  975. X                *adate ? date_to_ctime(adate) : fdate) == EOF)
  976. X#endif /* MSG_SEPARATOR */
  977. X            {
  978. X            art_cnt = -1;
  979. X            goto handle_error;
  980. X            }
  981. X            /* Make sure there is a From: without a leading > */
  982. X            if (*afrom && *from_hdr && fputs(from_hdr, fp) == EOF) {
  983. X            art_cnt = -1;
  984. X            goto handle_error;
  985. X            }
  986. X            get_hdr = 0L;
  987. X        } else if (on_hdr < 0)
  988. X            /* Skip blanks between "--------" and the hdr */
  989. X            get_hdr = ftell(tmpf);
  990. X        } else if (on_hdr < 0)
  991. X        on_hdr = 1;
  992. X        if (on_hdr > 0 && !strncmp(p, "From: ", 6)) {
  993. X        (void) get_name_n_addr(p + 6, NULL, afrom);
  994. X        (void) no_newln(afrom);
  995. X        /* Get the From: minus the leading > */
  996. X        if (p != line)
  997. X            (void) strcpy(from_hdr, p);
  998. X        else /* We don't need From: twice! */
  999. X            *from_hdr = '\0';
  1000. X        } else if (on_hdr > 0 && !strncmp(line, "Date: ", 6)) {
  1001. X        if (p = parse_date(line+6))
  1002. X            (void) strcpy(adate, p);
  1003. X        } else if (on_hdr > 0 && !lcase_strncmp(line, "end", 3)) {
  1004. X        if (!*afrom && !*adate)
  1005. X            break;
  1006. X        }
  1007. X    } else if (fputs(line, fp) == EOF) {
  1008. X        /* Pipe broken, out of file space, etc */
  1009. X        art_cnt = -1;
  1010. X        goto handle_error;
  1011. X    }
  1012. X    }
  1013. X    ++art_cnt;
  1014. X#ifdef END_MSG_SEP
  1015. X    if (art_cnt > 0 && fputs(END_MSG_SEP, fp) == EOF) {
  1016. X    art_cnt = -1;
  1017. X    goto handle_error;
  1018. X    }
  1019. X#endif /* END_MSG_SEP */
  1020. X    /* If we're still looking for a header, there is some stuff left
  1021. X     * at the end of the digest.  Create an extra article for it.
  1022. X     */
  1023. X    if (get_hdr) {
  1024. X    char *p;
  1025. X    (void) fseek(tmpf, get_hdr, L_SET);
  1026. X    if (ftell(tmpf) >= msg[n].m_offset + msg[n].m_size)
  1027. X        goto handle_error;
  1028. X#ifdef MSG_SEPARATOR
  1029. X#ifdef MMDF
  1030. X    if (fputs(MSG_SEPARATOR, fp) == EOF)
  1031. X#else /* !MMDF */
  1032. X    if (fputs(MSG_SEPARATOR, fp) == EOF ||
  1033. X        fputc('\n', fp) == EOF)
  1034. X#endif /* MMDF */
  1035. X#else /* !MSG_SEPARATOR */
  1036. X    if (fputs(from, fp) == EOF)
  1037. X#endif /* MSG_SEPARATOR */
  1038. X        art_cnt = -1;
  1039. X    if (!(p = header_field(n, "from")))
  1040. X        p = "Mush-Undigest (Real author unknown)";
  1041. X    if (fprintf(fp, "From: %s\n", p) == EOF)
  1042. X        art_cnt = -1;
  1043. X    if (!(p = header_field(n, "date")))
  1044. X        p = fdate, no_newln(p);
  1045. X    if (fprintf(fp, "Date: %s\n", p) == EOF)
  1046. X        art_cnt = -1;
  1047. X    if (!(p = header_field(n, "subject")))
  1048. X        p = "Digest";
  1049. X    if (fprintf(fp, "Subject: Trailing part of %s\n\n", p) == EOF)
  1050. X        art_cnt = -1;
  1051. X    /* header_field() moves the pointer, so seek again */
  1052. X    (void) fseek(tmpf, get_hdr, L_SET);
  1053. X    while (art_cnt > 0 && ftell(tmpf) < msg[n].m_offset + msg[n].m_size
  1054. X        && fgets(line, sizeof (line), tmpf)) {
  1055. X        if (fputs(line, fp) == EOF)
  1056. X        art_cnt = -1;
  1057. X#ifdef END_MSG_SEP
  1058. X        if (!strncmp(line, END_MSG_SEP, strlen(END_MSG_SEP)))
  1059. X        break;
  1060. X#endif /* END_MSG_SEP */
  1061. X    }
  1062. X    /* The END_MSG_SEP, if any, of the digest will have been output
  1063. X     * by the while loop above, so we don't need to add one here.
  1064. X     */
  1065. X    ++art_cnt;
  1066. X    }
  1067. Xhandle_error:
  1068. X    if (art_cnt == -1)
  1069. X    error("cannot completely undigest");
  1070. X    else if (ison(glob_flags, WAS_INTR))
  1071. X    art_cnt = -1;
  1072. X    off_intr();
  1073. X    return art_cnt;
  1074. X}
  1075. END_OF_FILE
  1076. if test 16743 -ne `wc -c <'folders.c'`; then
  1077.     echo shar: \"'folders.c'\" unpacked with wrong size!
  1078. fi
  1079. # end of 'folders.c'
  1080. fi
  1081. if test -f 'init.c' -a "${1}" != "-c" ; then 
  1082.   echo shar: Will not clobber existing file \"'init.c'\"
  1083. else
  1084. echo shar: Extracting \"'init.c'\" \(15373 characters\)
  1085. sed "s/^X//" >'init.c' <<'END_OF_FILE'
  1086. X/* init.c    (c) copyright 1986 (Dan Heller) */
  1087. X
  1088. X/* init.c -- functions and whatnot that initialize everything */
  1089. X#include "mush.h"
  1090. X#include <pwd.h>
  1091. X
  1092. X#ifdef SUNTOOL
  1093. X/* mouse symbols */
  1094. Xshort dat_mouse_left[] = {
  1095. X#include <images/confirm_left.pr> 
  1096. X};
  1097. X
  1098. Xshort dat_mouse_middle[] = {
  1099. X#include <images/confirm_middle.pr> 
  1100. X};
  1101. X
  1102. Xshort dat_mouse_right[] = {
  1103. X#include <images/confirm_right.pr> 
  1104. X};
  1105. X
  1106. Xshort dat_mail_icon_1[] = {
  1107. X#include "mail.icon.1"
  1108. X};
  1109. X
  1110. Xshort dat_mail_icon_2[] = {
  1111. X#include "mail.icon.2"
  1112. X};
  1113. X
  1114. Xshort dat_coffee_cup[] = {
  1115. X#include "coffee.cup.pr"
  1116. X};
  1117. X
  1118. Xshort dat_read_cursor[] = {
  1119. X#include "glasses.pr"
  1120. X};
  1121. X
  1122. Xshort dat_write_cursor[] = {
  1123. X#include "write.pr"
  1124. X};
  1125. X
  1126. Xshort dat_up_arrow[] = {
  1127. X#include "up.arrow.pr"
  1128. X};
  1129. X
  1130. Xshort dat_dn_arrow[] = {
  1131. X#include "dn.arrow.pr"
  1132. X};
  1133. X
  1134. Xshort dat_envelope[] = {
  1135. X#include "envelope.pr"
  1136. X};
  1137. X
  1138. Xshort dat_cycle_cursor[] = {
  1139. X#include "cycle.pr"
  1140. X};
  1141. X
  1142. Xshort dat_check_cursor[] = {
  1143. X#include "check.pr"
  1144. X};
  1145. X
  1146. Xmpr_static(mail_icon_image1, 64, 64, 1, dat_mail_icon_1);
  1147. Xmpr_static(mail_icon_image2, 64, 64, 1, dat_mail_icon_2);
  1148. X
  1149. Xmpr_static(mouse_left,      16, 16, 1, dat_mouse_left);
  1150. Xmpr_static(mouse_middle,    16, 16, 1, dat_mouse_middle);
  1151. Xmpr_static(mouse_right,     16, 16, 1, dat_mouse_right);
  1152. Xmpr_static(coffee_cup,      16, 16, 1, dat_coffee_cup);
  1153. Xmpr_static(glasses_cursor,  16, 16, 1, dat_read_cursor);
  1154. Xmpr_static(pencil_cursor,   16, 16, 1, dat_write_cursor);
  1155. Xmpr_static(up_arrow,        16, 16, 1, dat_up_arrow);
  1156. Xmpr_static(dn_arrow,        16, 16, 1, dat_dn_arrow);
  1157. Xmpr_static(envelope_cursor, 16, 16, 1, dat_envelope);
  1158. Xmpr_static(cycle,           16, 16, 1, dat_cycle_cursor);
  1159. Xmpr_static(check_cursor,    16, 16, 1, dat_check_cursor);
  1160. X
  1161. Xstruct cursor l_cursor     = { 3, 3, PIX_SRC,         &mouse_left      };
  1162. Xstruct cursor m_cursor     = { 3, 3, PIX_SRC,         &mouse_middle    };
  1163. Xstruct cursor r_cursor     = { 3, 3, PIX_SRC,         &mouse_right     };
  1164. Xstruct cursor coffee       = { 8, 8, PIX_SRC,         &coffee_cup      };
  1165. Xstruct cursor read_cursor  = { 8, 8, PIX_SRC|PIX_DST, &glasses_cursor  };
  1166. Xstruct cursor write_cursor = { 8, 8, PIX_SRC|PIX_DST, &pencil_cursor   };
  1167. Xstruct cursor main_cursor  = { 8, 8, PIX_SRC,         &envelope_cursor };
  1168. Xstruct cursor checkmark = { 8, 8, PIX_SRC|PIX_DST, &check_cursor };
  1169. X
  1170. X/* text and font will be set in mail_status() */
  1171. Xstruct icon mail_icon = { 64,  64, (struct pixrect *)NULL,
  1172. X            { 0, 0, 64, 64 }, &mail_icon_image1,
  1173. X            { 5, 5, 26, 12 }, NULL, (struct pixfont *)NULL, 0 };
  1174. X
  1175. Xchar *font_files[] = {
  1176. X    "serif.r.14", "sail.r.6", "serif.r.16",
  1177. X};
  1178. X
  1179. Xchar *alt_fonts[] = {
  1180. X    "gacha.r.8", "sail.r.6", "screen.r.14",
  1181. X};
  1182. X
  1183. X#endif /* SUNTOOL */
  1184. X
  1185. X#ifdef BSD
  1186. X#include <netdb.h>
  1187. X#endif /* BSD */
  1188. X
  1189. X#ifdef SYSV
  1190. X#include <sys/utsname.h>
  1191. X#endif /* SYSV */
  1192. X
  1193. Xvoid
  1194. Xinit()
  1195. X{
  1196. X    char         *home, *realname, *argv[4];
  1197. X    extern char        *getlogin(), **calloc();
  1198. X    char        buf[MAXPATHLEN];
  1199. X#ifdef SYSV
  1200. X    extern struct passwd *getpwuid();  /* sys-v forgot this in pwd.h! */
  1201. X    struct utsname ourhost;
  1202. X#else
  1203. X    char ourhost[128];
  1204. X#endif /* SYSV */
  1205. X    register char     *p;
  1206. X    struct passwd     *entry;
  1207. X    int            cnt;
  1208. X#ifdef BSD
  1209. X    struct hostent     *hp;
  1210. X#endif /* BSD */
  1211. X
  1212. X    home = getenv("HOME");
  1213. X    realname = getenv("NAME");
  1214. X    argv[1] = "=";
  1215. X    argv[3] = NULL;
  1216. X
  1217. X    if (!(entry = getpwuid(getuid())))
  1218. X    if (p = getlogin())
  1219. X        strdup(login, p);
  1220. X    else {
  1221. X        login = "unknown";
  1222. X        print("I don't know you, but that's ok.\n");
  1223. X    }
  1224. X    else {
  1225. X    strdup(login, entry->pw_name);
  1226. X    if (!home || !*home)
  1227. X        home = entry->pw_dir;
  1228. X    if (!realname && (realname = entry->pw_gecos) &&
  1229. X        (p = index(realname, ',')))
  1230. X        *p = 0;
  1231. X    endpwent();
  1232. X    }
  1233. X    if (!home || !*home || Access(home, W_OK)) {
  1234. X    if (home && *home)
  1235. X        error(home);
  1236. X    else
  1237. X        print("No home!? ");
  1238. X    print_more("Using \"%s\" as home.\n", ALTERNATE_HOME);
  1239. X    } else {
  1240. X    argv[0] = "home";
  1241. X    argv[2] = home;
  1242. X    (void) add_option(&set_options, argv);
  1243. X    }
  1244. X    if (realname) {
  1245. X    if (realname == entry->pw_gecos) {
  1246. X        for (p = buf; *realname; realname++)
  1247. X        if (*realname == '&')
  1248. X            *p++ = upper(*login), p += Strcpy(p, login+1);
  1249. X        else
  1250. X            *p++ = *realname;
  1251. X        *p = 0;
  1252. X    } else
  1253. X        (void) strcpy(buf, realname);
  1254. X    argv[0] = "realname";
  1255. X    argv[2] = buf;
  1256. X    (void) add_option(&set_options, argv);
  1257. X    }
  1258. X    crt = 24;
  1259. X    screen = 18;
  1260. X    wrapcolumn = 0; /* Default is no wrap */
  1261. X    escape = DEF_ESCAPE;
  1262. X    prompt = DEF_PROMPT;
  1263. X
  1264. X#ifdef BSD
  1265. X    (void) gethostname(ourhost, sizeof ourhost);
  1266. X    if (!(hp = gethostbyname(ourhost))) {
  1267. X    error("gethostbyname: %s", ourhost);
  1268. X    if (ourname = calloc((unsigned)2, sizeof (char *)))
  1269. X        strdup(ourname[0], ourhost);
  1270. X    } else {
  1271. X    int n = 0;
  1272. X    cnt = 2; /* 1 for ourhost and 1 for NULL terminator */
  1273. X    for (p = hp->h_name; p && *p; p = hp->h_aliases[n++])
  1274. X        if (strcmp(ourhost, p)) /* if host name is different */
  1275. X        cnt++;
  1276. X    if (ourname = calloc((unsigned)cnt, sizeof (char *))) {
  1277. X        ourname[--cnt] = NULL;
  1278. X        for (p = hp->h_name; p && *p && n >= 0; p = hp->h_aliases[--n])
  1279. X        if (strcmp(ourhost, p)) /* if host name is different */
  1280. X            ourname[--cnt] = savestr(p);
  1281. X        strdup(ourname[0], ourhost); /* cnt better be 0! */
  1282. X    }
  1283. X    }
  1284. X    endhostent();
  1285. X#endif /* BSD */
  1286. X#ifdef SYSV
  1287. X    ourname = calloc((unsigned)2, sizeof (char *));
  1288. X    if ((uname (&ourhost) >= 0) && (*ourhost.nodename))
  1289. X    ourname[0] = savestr(ourhost.nodename);
  1290. X    else {
  1291. X        /* Try to use uuname -l to get host's name if uname didn't work */
  1292. X        char buff[50];
  1293. X        char *p;
  1294. X        FILE *F;
  1295. X
  1296. X        if (F = popen("exec uuname -l", "r")) {
  1297. X            if ((fgets(buff, sizeof buff, F) == buff) &&
  1298. X                (p = strchr(buff, '\n'))) {
  1299. X            *p = '\0';        /* eliminate newline */
  1300. X        ourname[0] = savestr (buff);
  1301. X        }
  1302. X    (void)pclose(F);
  1303. X        }
  1304. X    }
  1305. X#endif /* SYSV */
  1306. X    if (ourname && ourname[0]) {
  1307. X    for (p = buf, cnt = 0; ourname[cnt]; cnt++) {
  1308. X        if (cnt)
  1309. X        *p++ = ' ';
  1310. X        p += Strcpy(p, ourname[cnt]);
  1311. X    }
  1312. X    argv[0] = "hostname";
  1313. X    argv[2] = buf;
  1314. X    (void) add_option(&set_options, argv);
  1315. X    }
  1316. X    init_bindings();
  1317. X}
  1318. X
  1319. X/*
  1320. X * Source a file, or just the default file.  Since sourcing files
  1321. X * means reading possible aliases, don't expand the ! as history
  1322. X * by setting the IGN_BANG flag.  Since a command in the sourced file
  1323. X * may call source on another file, this routine may be called from
  1324. X * within itself.  Continue to ignore ! chars by setting save_bang (local).
  1325. X *
  1326. X * Try opening the file passed to us.  If not given, check for the correct
  1327. X * .rc file which is found in the user's home dir.
  1328. X */
  1329. Xsource(argc, argv)
  1330. Xchar **argv;
  1331. X{
  1332. X    register char *p;
  1333. X    FILE      *fp;
  1334. X    char       file[128];
  1335. X    u_long      save_bang = ison(glob_flags, IGN_BANG);
  1336. X    int          line_no = 0;
  1337. X
  1338. X    if (argc && *++argv && !strcmp(*argv, "-?"))
  1339. X    return help(0, "source", cmd_help);
  1340. X    if (argc && *argv)
  1341. X    (void) strcpy(file, *argv);
  1342. X    else if (p = getenv("MAILRC"))
  1343. X    (void) strcpy(file, p);
  1344. X    else {
  1345. X    char *home = do_set(set_options, "home");
  1346. X    if (!home || !*home)
  1347. X        home = ALTERNATE_HOME;
  1348. X    if (Access(sprintf(file, "%s/%s", home, MAILRC), R_OK)
  1349. X          && Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), R_OK))
  1350. X    (void) strcpy(file, DEFAULT_RC);
  1351. X    }
  1352. X
  1353. X    argc = 0; /* don't ignore ENOENT */
  1354. X    p = getpath(file, &argc);
  1355. X    if (argc) {
  1356. X    if (strcmp(file, DEFAULT_RC))
  1357. X        if (argc == -1)
  1358. X        print("%s: %s\n", file, p);
  1359. X        else
  1360. X        print("%s is a directory.\n", file);
  1361. X    return -1;
  1362. X    }
  1363. X    if (!(fp = fopen(p, "r"))) {
  1364. X    if (errno != ENOENT)
  1365. X        error("Can't open %s", p);
  1366. X    return -1;
  1367. X    }
  1368. X    turnon(glob_flags, IGN_BANG); /* ignore ! when reading record files */
  1369. X    (void) strcpy(file, p);
  1370. X    (void) src_parse(file, fp, 0, 0, &line_no);
  1371. X    /* if we entered the routine ignoring !, leave it that way. */
  1372. X    if (!save_bang)
  1373. X    turnoff(glob_flags, IGN_BANG);
  1374. X    /* Sourcing might change things, so abort pipes/macros */
  1375. X    return 0 - (in_pipe() || in_macro());
  1376. X}
  1377. X
  1378. X/*
  1379. X * Do the actual file parsing for source().  The first argument should
  1380. X * be the name of the file referenced by the second argument.  The third
  1381. X * argument is used for handling nested if_else_endif expressions.  The
  1382. X * fourth argument is used to keep track of the recursion depth, and the
  1383. X * last argument keeps track of the line number in the current file.
  1384. X *
  1385. X * This function calls itself recursively.  It also calls do_command(),
  1386. X * which may in turn call source() recursively.
  1387. X *
  1388. X * If-then-else nesting algorithm:
  1389. X *  On any "if" (whether parsing or not), increment if_else
  1390. X *  On true "if" when parsing, evaluate by recursion
  1391. X *  On false "if" when parsing, set find_else equal to if_else
  1392. X *  On any "if" when not parsing, set find_endif equal to if_else
  1393. X *  On "else", invert parsing only when find_else equals if_else
  1394. X *  When "if" was false and there is nesting, recur for "else"
  1395. X *  Skip nested "if...endif" when find_else or find_endif true
  1396. X *  On "endif" or when recursion returns, decrement if_else
  1397. X *  On "endif", test both find_endif and find_else against if_else:
  1398. X *   when either matches, reset that one;
  1399. X *   when the lesser (less nested) matches, resume parsing
  1400. X *  On "endif", when if_else hits 0, continue (depth 0) or return
  1401. X */
  1402. Xsrc_parse(file, fp, if_else, depth, line_no)
  1403. Xchar    *file;
  1404. XFILE    *fp;
  1405. Xint      if_else, depth, *line_no;
  1406. X{
  1407. X    register char *p, *p2, **newargv;
  1408. X    int       parsing = 1, cont_line = 0;
  1409. X    int          find_else = 0, find_endif = 0;
  1410. X    char       line[BUFSIZ];
  1411. X    int          argc;
  1412. X
  1413. X    while (p = fgets(&line[cont_line], BUFSIZ - cont_line, fp)) {
  1414. X    (*line_no)++;
  1415. X    if (*(p2 = no_newln(p)) == '\\') {
  1416. X        cont_line = p2 - line;
  1417. X        continue;
  1418. X    } else
  1419. X        cont_line = 0;
  1420. X    /* don't consider comments (#) in lines. check if # is within quotes */
  1421. X        if (p = any(line, "\"'#")) {
  1422. X        register int balanced = 1;
  1423. X        while (p && (*p == '\'' || *p == '"') && balanced) {
  1424. X        /* first find matching quote */
  1425. X        register char *quote = index(p+1, *p);
  1426. X        if (!quote) {
  1427. X            print("%s: line %d: unbalanced %c.\n", file, *line_no, *p);
  1428. X            balanced = 0;
  1429. X        } else
  1430. X            p = any(quote+1, "'\"#");
  1431. X        }
  1432. X        if (!balanced)
  1433. X        continue;
  1434. X        if (p && *p == '#')
  1435. X        *p = 0; /* found a Comment: null terminate line at comment */
  1436. X    }
  1437. X    if (!*line || !parsing && !(newargv = mk_argv(line, &argc, 0))
  1438. X    || parsing && !(newargv = make_command(line, TRPL_NULL, &argc))) {
  1439. X        if (!strncmp(line, "if", 2))
  1440. X        find_else = ++if_else, parsing = FALSE;
  1441. X        continue;
  1442. X    }
  1443. X    if (!strcmp(newargv[0], "endif")) {
  1444. X        if (!if_else)
  1445. X        print("%s: line %d: endif with no \"if\".\n", file, *line_no);
  1446. X        else {
  1447. X        /* If looking for an else or endif, reset parsing */
  1448. X        if (find_endif && find_endif == if_else) {
  1449. X            if (find_endif <= find_else || !find_else)
  1450. X            parsing = 1, find_else = 0;
  1451. X            find_endif = 0;
  1452. X        }
  1453. X        /* Note: find_else never < find_endif */
  1454. X        if (find_else && find_else == if_else)
  1455. X            parsing = !parsing, find_else = 0;
  1456. X        /* Decrement if_else and check depth */
  1457. X        if (--if_else == 0)
  1458. X            /* Resume parsing if at the top */
  1459. X            if (depth == 0)
  1460. X            parsing = 1;
  1461. X            /* Return if not at the top */
  1462. X            else
  1463. X            return 1;
  1464. X        }
  1465. X        goto bad;
  1466. X    } else if (!strcmp(newargv[0], "else")) {
  1467. X        if (!if_else)
  1468. X        print("%s: line %d: if-less \"else\".\n", file, *line_no);
  1469. X        /* If inside an else, ignore nested else;
  1470. X         *  otherwise, recur when if_else > 1 */
  1471. X        else if (!find_else && !find_endif && !parsing) {
  1472. X        parsing = src_parse(file, fp, 1, depth + 1, line_no);
  1473. X        --if_else;
  1474. X        } else if (find_else == if_else || if_else == 1) {
  1475. X        find_else = 0;
  1476. X        parsing = !parsing;
  1477. X        if (!parsing)
  1478. X            find_endif = if_else;
  1479. X        }
  1480. X        goto bad;
  1481. X    } else if (!strcmp(newargv[0], "if")) {
  1482. X        /* if statements are of the form:
  1483. X         *     if expr
  1484. X         *     if !expr  or  if ! expr
  1485. X         *     if expr == expr   or   if expr != expr
  1486. X         */
  1487. X        int equals = TRUE;
  1488. X        register char *lhs = newargv[1], *rhs = NULL;
  1489. X
  1490. X        if_else++;
  1491. X        /* If parsing, set parsing to 0 until
  1492. X         *  evaluating the "if" proves otherwise.
  1493. X         * If not parsing, skip to the "endif".
  1494. X         */
  1495. X        if (parsing)
  1496. X        parsing = 0;
  1497. X        else {
  1498. X        if (!find_endif)
  1499. X            find_endif = if_else;
  1500. X        goto bad;
  1501. X        }
  1502. X        if (!lhs || !*lhs) {
  1503. X        print("%s: line %d: if what?\n", file, *line_no);
  1504. X        goto bad;
  1505. X        }
  1506. X        /* "lhs" is the left hand side of the equation
  1507. X         * In this instance, we're doing case 2 above (check for negation).
  1508. X         */
  1509. X        if (*lhs == '!') {
  1510. X        if (!*++lhs && !(lhs = newargv[2])) {
  1511. X            print("%s: line %d: syntax error: \"if ! <what?>\"\n",
  1512. X            file, *line_no);
  1513. X            goto bad;
  1514. X        }
  1515. X        equals = FALSE;
  1516. X        }
  1517. X        if (*lhs == '-' && (lhs[1] == 'e' || lhs[1] == 'z') && !lhs[2]) {
  1518. X        char *path;
  1519. X        int n = 1; /* ignore ENOENT, I'll handle it here */
  1520. X        struct stat statb;
  1521. X
  1522. X        /* check for existence or zero-length folders/files */
  1523. X        if (argc > 4) {
  1524. X            print("%s: line %d: if %s \"filename\"\n",
  1525. X            file, *line_no, lhs);
  1526. X            goto bad;
  1527. X        }
  1528. X        path = getpath(newargv[argc-1], &n);
  1529. X        parsing = !equals ^ (n == -1 || n == 1 && lhs[1] == 'e' ||
  1530. X            !stat(path, &statb) && (lhs[1] == 'e' || !statb.st_size));
  1531. X        } else {
  1532. X        if (equals && argc > 2) {
  1533. X            if (argc != 4) {
  1534. X            print("%s: %d: argument count error: %d args.\n",
  1535. X                file, *line_no, argc);
  1536. X            goto bad;
  1537. X            }
  1538. X            /* now check newargv[1] for == or != */
  1539. X            if (!strcmp(newargv[2], "!="))
  1540. X            equals = FALSE;
  1541. X            else if (strcmp(newargv[2], "==")) {
  1542. X            print("%s: %d: use `==' or `!=' only.\n",
  1543. X                file, *line_no);
  1544. X            goto bad;
  1545. X            }
  1546. X            rhs = newargv[3];
  1547. X        }
  1548. X        if (!strcmp(lhs, "redirect") &&
  1549. X              (ison(glob_flags, REDIRECT) && equals ||
  1550. X               isoff(glob_flags, REDIRECT) && !equals)
  1551. X            || !strcmp(lhs, "is_sending") &&
  1552. X              (ison(glob_flags, IS_SENDING) && equals ||
  1553. X               isoff(glob_flags, IS_SENDING) && !equals)
  1554. X            || !strcmp(lhs, "hdrs_only") &&
  1555. X              (hdrs_only && equals || !hdrs_only && !equals)
  1556. X            || !strcmp(lhs, "istool") &&
  1557. X              (istool && equals || !istool && !equals)
  1558. X            || !strcmp(lhs, "iscurses") &&
  1559. X              ((iscurses || ison(glob_flags, PRE_CURSES)) && equals
  1560. X              || (isoff(glob_flags, PRE_CURSES) &&
  1561. X                  !iscurses && !equals)))
  1562. X            parsing = 1;
  1563. X        else if (rhs) {
  1564. X            if (strcmp(lhs, rhs) && !equals
  1565. X            || !strcmp(lhs, rhs) && equals)
  1566. X            parsing = 1;
  1567. X        } else if (isdigit(*lhs))
  1568. X            parsing = !!(atoi(lhs) ? equals : !equals);
  1569. X        }
  1570. X        if (parsing) {
  1571. X        parsing = src_parse(file, fp, 1, depth + 1, line_no);
  1572. X        --if_else;
  1573. X        }
  1574. X        else
  1575. X        find_else = if_else; /* Look for a matching else */
  1576. Xbad:
  1577. X        free_vec(newargv);
  1578. X        continue;
  1579. X    }
  1580. X    if (parsing && argc > 0)
  1581. X        if (!strcmp(newargv[0], "exit")) {
  1582. X        if_else = find_else = find_endif = 0;
  1583. X        break;
  1584. X        } else
  1585. X        (void) do_command(argc, newargv, msg_list);
  1586. X    else
  1587. X        free_vec(newargv);
  1588. X    }
  1589. X    if (if_else)
  1590. X    print("%s: missing endif\n", file);
  1591. X    if (depth == 0)
  1592. X    fclose(fp);
  1593. X    else
  1594. X    fseek(fp, 0L, 2); /* Skip ahead to the end */
  1595. X    return 0;
  1596. X}
  1597. X
  1598. X#ifdef SUNTOOL
  1599. X/* open all fonts and place in fonts array. */
  1600. Xgetfonts()
  1601. X{
  1602. X    char tmp[80];
  1603. X    register int offset = strlen(FONTDIR) + 1;
  1604. X    struct pixfont *pf_open();
  1605. X
  1606. X    (void) sprintf(tmp, "%s/", FONTDIR);
  1607. X    for (total_fonts = 0; total_fonts < MAX_FONTS; total_fonts++) {
  1608. X    (void) strcpy(&tmp[offset], font_files[total_fonts]);
  1609. X    if (!(fonts[total_fonts] = pf_open(tmp))) {
  1610. X        (void) strcpy(&tmp[offset], alt_fonts[total_fonts]);
  1611. X        if (!(fonts[total_fonts] = pf_open(tmp))) {
  1612. X        print("couldn't open font \"%s\"\n", tmp);
  1613. X        fonts[total_fonts] = pf_default();
  1614. X        }
  1615. X    }
  1616. X    }
  1617. X}
  1618. X#endif /* SUNTOOL */
  1619. END_OF_FILE
  1620. if test 15373 -ne `wc -c <'init.c'`; then
  1621.     echo shar: \"'init.c'\" unpacked with wrong size!
  1622. fi
  1623. # end of 'init.c'
  1624. fi
  1625. echo shar: End of archive 7 \(of 19\).
  1626. cp /dev/null ark7isdone
  1627. MISSING=""
  1628. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1629.     if test ! -f ark${I}isdone ; then
  1630.     MISSING="${MISSING} ${I}"
  1631.     fi
  1632. done
  1633. if test "${MISSING}" = "" ; then
  1634.     echo You have unpacked all 19 archives.
  1635.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1636. else
  1637.     echo You still need to unpack the following archives:
  1638.     echo "        " ${MISSING}
  1639. fi
  1640. ##  End of shell archive.
  1641. exit 0
  1642.